package com.lib.smartimage;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;

import com.lib.utils.CloseUtils;
import com.lib.utils.FileUtils;
import com.lib.utils.ImageUtils;
import com.lib.utils.XLog;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.ref.SoftReference;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class WebSmartImageCache {
    private static final String DISK_CACHE_PATH = "/cache_image/";

    private ConcurrentHashMap<String, SoftReference<Bitmap>> mMemoryCache;

    private String mCachePath;

    private boolean mCacheEnable;

    private ExecutorService mWriteThread;

    public WebSmartImageCache() {
        mMemoryCache = new ConcurrentHashMap<>();
        mWriteThread = Executors.newSingleThreadExecutor();

        mCachePath = FileUtils.getCacheDir(XLog.sContext).getAbsolutePath() + DISK_CACHE_PATH;
        File outFile = new File(mCachePath);
        if (!outFile.exists()) {
            outFile.mkdirs();
        }
        mCacheEnable = outFile.exists();
    }

    public Bitmap getBitmap(String url, int width) {
        Bitmap bitmap = getBitmapFromMemory(url);

        // Check for image on disk cache
        if (bitmap == null ||
                (bitmap.getWidth() == 0 && bitmap.getHeight() == 0)) {
            bitmap = getBitmapFromDisk(url, width);

            // Write bitmap back into memory cache
            if (bitmap != null) {
                cacheBitmapToMemory(url, bitmap);
            }
        }
        return bitmap;
    }

    public void cacheBitmapToMemory(final String url, final Bitmap bitmap) {
        mMemoryCache.put(getCacheKey(url), new SoftReference<>(bitmap));
    }

    public void cacheBitmapToDisk(final String url, final Bitmap bitmap) {
        if (mCacheEnable) {
            mWriteThread.execute(new Runnable() {

                @Override
                public void run() {
                    BufferedOutputStream bos = null;
                    FileOutputStream out = null;
                    try {
                        File file = new File(mCachePath, getCacheKey(url));
                        out = new FileOutputStream(file);
                        bos = new BufferedOutputStream(out, 2 * 1024);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
                        bos.flush();
                    } catch (Exception e) {//
                    } finally {
                        CloseUtils.closeIOQuietly(out, bos);
                    }
                }
            });
        }
    }

    private Bitmap getBitmapFromMemory(String url) {
        SoftReference<Bitmap> softRef = mMemoryCache.get(getCacheKey(url));
        if (softRef != null) {
            return softRef.get();
        }
        return null;
    }

    /**
     * @param url   获取bitmap 的地址
     * @param width 最大显示的尺寸 宽
     */
    private Bitmap getBitmapFromDisk(String url, int width) {
        Bitmap bitmap = null;
        if (mCacheEnable) {
            if (width > 0) {
                bitmap = ImageUtils.getBitmapFromFile(url, width);
            } else {
                bitmap = BitmapFactory.decodeFile(mCachePath + getCacheKey(url));
            }
        }

        if (bitmap == null) {
            if (width > 0) {
                bitmap = ImageUtils.getBitmapFromFile(url, width);
            } else {
                bitmap = BitmapFactory.decodeFile(url);
            }
        }
        return bitmap;
    }

    public void remove(String url) {
        if (url == null) {
            return;
        }

        // Remove from memory cache
        mMemoryCache.remove(getCacheKey(url));

        // Remove from file cache
        File f = new File(mCachePath, getCacheKey(url));
        if (f.exists() && f.isFile()) {
            f.delete();
        }
    }

    public void clear() {
        // Remove everything from memory cache
        mMemoryCache.clear();

        // Remove everything from file cache
        File cachedFileDir = new File(mCachePath);
        if (cachedFileDir.exists() && cachedFileDir.isDirectory()) {
            File[] cachedFiles = cachedFileDir.listFiles();
            for (File f : cachedFiles) {
                if (f.exists() && f.isFile()) {
                    f.delete();
                }
            }
        }
    }

    private String getCacheKey(String url) {
        if (TextUtils.isEmpty(url.trim())) {
            return "";
        }
        return String.valueOf(url.hashCode());
    }
}